package eiisan.reflect;

/**
 * 首先用文字简单描述一下Java 类的初始化顺序（此处引用 Core Java Volume I 中的译文）
 *
 * 规则1：在类第一次加载的时候，将会进行静态域的初始化：
 * 1. 将所有的静态数据域初始化为默认值（0、false 和 null）
 * 2. 按照在类中定义的顺序依次执行静态初始化语句和静态初始化块
 *
 * 规则2：调用构造器的具体处理步骤：
 * 1. 将所有的数据域初始化为默认值（0、false 和 null）
 * 2.按照在类中定义的顺序依次执行初始化语句和初始化块
 * 3. 如果构造器调用的其他的构造器，则转而执行另一构造器
 * 4. 执行构造器主体
 * 下面
 * 1. 首先类被加载，类中所有的静态域被初始化为0、false 或 null（注意这里并没有执行初始化语句，千万要搞明白初始化语句这里的区别）。
 * 变量状态：k, i, n = 0; t1, t2 = null
 * 2. 然后依照定义次序执行类中的静态域初始化语句和静态初始化块
 * 3. 执行到静态初始化语句public static Test t1 = new Test("t1"); 时，调用构造器（这里类不会再次加载），这是会产生一个新对象 t1，对新对象执行上面说的步骤1。
 * 4. 对象 t1 初始化输出为：
 * Plain代码
 * 1:j   i=0    n=0
 * 2:构造块   i=1    n=1
 * 3:t1   i=2    n=2
 *
 * 5. 对象 t1 构造完毕后，接下来构造 t2，过程和上面相同，这一步骤的输出为：
 * Plain代码
 * 4:j   i=3    n=3
 * 5:构造块   i=4    n=4
 * 6:t2   i=5    n=5
 *
 * 6. 然后执行public static int i = print("i"); 和静态初始化块，输出：
 * Plain代码
 * 7:i   i=6    n=6
 * 8:静态块   i=7    n=99
 *
 * 7. 至此，类加载完毕，接下来便是 main 函数中的对象 t 的构造，构造过程为步骤 1。输出为：
 * Plain代码
 * 9:j   i=8    n=100
 * 10:构造块   i=9    n=101
 * 11:init   i=10    n=102
 */

public class TestClassLode {
  
    public static int k = 0;  
    public static TestClassLode t1 = new TestClassLode("t1");
    public static TestClassLode t2 = new TestClassLode("t2");
    public static int n = 99;
    public static int i = print("i");

    static {
        print("静态块");
    }

    public int j = print("j");
    private int a = 0;

    {
        print("构造块");
    }
  
    public TestClassLode(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;  
        ++n;  
    }  
  
    public static int print(String str) {  
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++n;  
        return ++i;  
    }  
  
    public static void main(String[] args) {
        TestClassLode t = new TestClassLode("init");
        new TestClassLode("init2");
    }  
  
}  